package com.example.evennews.viewmodel

import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.evennews.bean.NewsDetail
import com.example.evennews.bean.NewsDetailResponse
import com.example.evennews.bean.NewsDigest
import com.example.evennews.bean.NewsDigestResponse
import com.example.evennews.bean.NewsItem
import com.example.evennews.model.NewsService
import com.example.evennews.bean.NewsType
import com.example.evennews.bean.NewsTypeResponse
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.time.delay
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.net.SocketTimeoutException
import java.util.concurrent.TimeUnit
import kotlin.math.log

class NewsViewmodel : ViewModel() {
    private val newsService: NewsService
    private val API_ID = "fnbn7xoxithiieth"
    private val API_SECRET = "gjcDqtB2YlkNgPlXhYdkQNTgyYIRd1cZ"

    //监视新闻类别加载进度
    private val _typeStatus = MutableLiveData<TypeStatus>(TypeStatus.LOADING)
    val typeStatus: LiveData<TypeStatus>
        get() = _typeStatus

    //监视新闻列表的加载进度
    private val _digestStatus = MutableLiveData<DigestStatus>(DigestStatus.LOADING)
    val digestStatus: LiveData<DigestStatus>
        get() = _digestStatus

    //监视新闻详情页的开关和加载进度
    private val _detailStatus = MutableLiveData<DetailStatus>(DetailStatus.CLOSED)
    val detailStatus: LiveData<DetailStatus>
        get() = _detailStatus


    //新闻类别列表
    private val _newsTypeStateFlow = MutableLiveData<List<NewsType>>(emptyList())
    val newsTypeStateFlow: LiveData<List<NewsType>>
        get() = _newsTypeStateFlow

    //新闻列表
    private val _newsDigestList = MutableLiveData<List<NewsDigest>>(emptyList())
    val newsDigestList: LiveData<List<NewsDigest>>
        get() = _newsDigestList

    //新闻详情items
    private val _newsItemsList= MutableLiveData<List<NewsItem>>(emptyList())
    val newsItemList:LiveData<List<NewsItem>>
        get() = _newsItemsList

    //缓存不同类别的新闻
    private val newsTypeMap = HashMap<String, List<NewsDigest>>()

    //此类别上次停留在第几页
    private val pagesMap = HashMap<String, Int>()

    //当前新闻类别index
    private val _currentType = MutableLiveData(-1)
    val currentType: LiveData<Int>
        get() = _currentType

    //当前在第几页
    private val _currentPage = MutableLiveData(0)
    val currentPage: LiveData<Int>
        get() = _currentPage

    //当前新闻详情显示的是哪个新闻
    private val _currentDigest = MutableLiveData(
        NewsDigest(
            "类别ID", "标题", "新闻概要",
            "新闻ID", "来源", "发布时间"
        )
    )
    val currentDigest: LiveData<NewsDigest>
        get() = _currentDigest


    init {
        val retrofit = Retrofit.Builder()
            .baseUrl("https://www.mxnzp.com/")  // 替换为实际的API基础地址
            // .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        newsService = retrofit.create(NewsService::class.java)


    }


    //给view调用的方法
    fun getNewsType() {
        _typeStatus.value = TypeStatus.LOADING
        viewModelScope.launch(Dispatchers.IO) {
            val call = newsService.getNewsType(API_ID, API_SECRET)
            Log.d("TAG", "getNewsType: " + call.request().url)
            //  call.execute()
            call.enqueue(object : Callback<NewsTypeResponse> {


                override fun onResponse(
                    call: Call<NewsTypeResponse>,
                    response: Response<NewsTypeResponse>
                ) {
                    response.body()?.let {
                        Log.d("TAG", "getNewsType: " + it.msg)
                        if (it.code == 1) {
                            setNewsTypeList(it.data)
                            _typeStatus.value = TypeStatus.SUCCEED
                            viewModelScope.launch(Dispatchers.Main) {
                                kotlinx.coroutines.delay(300)//接口不给请求太频繁
                                chooseType(0)
                            }

                        } else {
                            _typeStatus.value = TypeStatus.FAILED
                        }

                    }
                }

                override fun onFailure(call: Call<NewsTypeResponse>, t: Throwable) {
                    //TODO:失败提示
                    Log.d("TAG", "onFailure: " + t.stackTraceToString())
                    _typeStatus.value = TypeStatus.FAILED
                }

            })
        }

    }

    fun chooseType(typeIndex: Int) {

        _digestStatus.value = DigestStatus.LOADING
        if (!newsTypeStateFlow.value.isNullOrEmpty()) {

            val list = newsTypeStateFlow.value
            if (list != null) {
                if (typeIndex >= 0 && typeIndex < list.size) {
                    //改变digest列表
                    val typeId = list[typeIndex].typeId
                    val page = pagesMap[typeId] ?: 1
                    _currentType.value = typeIndex
                    _currentPage.value = page
                    //先取缓存再取网络
                    if (newsTypeMap.containsKey(typeId) && newsTypeMap[typeId] != null) {
                        val digests = newsTypeMap[typeId]
                        Log.d("TAG", "chooseType: 1")
                        setNewsDigestList(digests!!)
                        pagesMap.put(typeId, page)
                        _digestStatus.value = DigestStatus.SUCCEED
                    } else {
                        getNewsDigestFromNet(typeId, page)
                        Log.d("TAG", "chooseType: 2")
                    }


                }
            }
        }


    }

    fun turnPage(newPage: Int) {
        if (newPage >= 1) {
            _currentPage.value = newPage
            _newsTypeStateFlow.value?.let { types ->
                _currentType.value?.let { index ->
                    getNewsDigestFromNet(types[index].typeId, newPage)
                }
            }
        }
    }

    fun closeNewsDetail() {
        _detailStatus.value = DetailStatus.CLOSED
    }

    fun onRetryDetailItems() {
        _detailStatus.value = DetailStatus.OPENED_PRELOAD
    }

    fun openNewsDetail(digestIndex: Int) {
        _detailStatus.value = DetailStatus.OPENED_PRELOAD
        _newsDigestList.value?.let { list ->
            if (digestIndex >= 0 && digestIndex < list.size) {
                _currentDigest.value = list[digestIndex]
            }
        }

    }


    fun detailReadyLoading() {
        _detailStatus.value = DetailStatus.OPENED_LOADING
    }

    fun getNewsDetailItems(newsId: String){
        val call=newsService
            .getNewsDetail(newsId, API_ID, API_SECRET)
        viewModelScope.launch(Dispatchers.IO) {
            call.enqueue(object :Callback<NewsDetailResponse>{
                override fun onResponse(
                    call: Call<NewsDetailResponse>,
                    response: Response<NewsDetailResponse>
                ) {
//                    TODO("Not yet implemented")
                    response.body()?.let {
                        Log.d("TAG", "onFailure: detail"+it.msg)
                        if(it.code==1){
                            _newsItemsList.value=it.data.items
                            _detailStatus.value=DetailStatus.OPENED_SUCCEED

                        }else{
                            _detailStatus.value=DetailStatus.OPENED_FAILED
                        }
                    }
                }

                override fun onFailure(call: Call<NewsDetailResponse>, t: Throwable) {
//                    TODO("Not yet implemented")
                    Log.d("TAG", "onFailure: detail"+t.stackTraceToString())
                    _detailStatus.value=DetailStatus.OPENED_FAILED
                }

            })
        }

    }


    fun getNewsItems(newsId: String) = viewModelScope.async(Dispatchers.IO) {

        try {
            val response = newsService
                .getNewsDetail(newsId, API_ID, API_SECRET)
                .execute()
            response.body()?.let {
                Log.d("TAG", "onResponse:detail " + it.msg)
                if (it.code == 1) {
                    withContext(Dispatchers.Main) {
                        if(detailStatus.value==DetailStatus.OPENED_LOADING){
                            _detailStatus.value = DetailStatus.OPENED_SUCCEED
                        }


                    }
//                Log.d("TAG", "onResponse:detail "+it.data.items.toString())
                    it.data.items

                } else {
                    withContext(Dispatchers.Main) {
                        _detailStatus.value = DetailStatus.OPENED_FAILED

                    }
                    emptyList()
                }
            }
        } catch (e: SocketTimeoutException) {
            withContext(Dispatchers.Main) {
                _detailStatus.value = DetailStatus.OPENED_FAILED
                emptyList()
            }
        }


    }


    //私有方法
    private fun setNewsTypeList(list: List<NewsType>) {
        _newsTypeStateFlow.value = list
    }

    private fun getNewsDigestFromNet(typeId: String, page: Int) {
        _digestStatus.value = DigestStatus.LOADING

        viewModelScope.launch(Dispatchers.IO) {
            val call = newsService.getNewsDigest(typeId, page, API_ID, API_SECRET)
            Log.d("TAG", "getNewsDigestFromNet: ")

            call.enqueue(object : Callback<NewsDigestResponse> {
                override fun onResponse(
                    call: Call<NewsDigestResponse>,
                    response: Response<NewsDigestResponse>
                ) {
                    response.body()?.let {
                        if (it.code == 1) {
                            Log.d("TAG", "onResponse: " + it.msg)
                            setNewsDigestList(it.data)

                            //加入缓存
                            newsTypeMap[typeId] = it.data
                            pagesMap.put(typeId, page)
                            _digestStatus.value = DigestStatus.SUCCEED
                        } else {
                            Log.d("TAG", "onResponse: " + it.msg)
                            _digestStatus.value = DigestStatus.FAILED
                        }
                    }

                }

                override fun onFailure(call: Call<NewsDigestResponse>, t: Throwable) {
                    //TODO:失败提示
                    Log.d("TAG", "onFailure: " + t.stackTraceToString())
                    _digestStatus.value = DigestStatus.FAILED
                }

            })


        }

    }

    private fun setNewsDigestList(list: List<NewsDigest>) {
        _newsDigestList.value = list
    }

}